<!DOCTYPE html><html lang="zh-CN" data-theme="light"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width,initial-scale=1"><title>DockerFile常用指令 | LeDao的博客</title><meta name="keywords" content="Docker,DockerFile"><meta name="author" content="LeDao"><meta name="copyright" content="LeDao"><meta name="format-detection" content="telephone=no"><meta name="theme-color" content="#ffffff"><meta name="description" content="DockerFile简介dockerfile用于快速有序且直观地完成对镜像的定制 Dockerfile 是一个文本文件，其内包含了一条条的指令(Instruction)，每一条指令构建一层，因此每一条指令的内容，就是描述该层应当如何构建 指令FROMFROM指令是整个Dockerfile的入口，必须是第一条指令。其代表新制作镜像的基础镜像。基础镜像可以自己制作，也可以从开源的仓库pull，例如do">
<meta property="og:type" content="article">
<meta property="og:title" content="DockerFile常用指令">
<meta property="og:url" content="https://blog.zoutl.cn/304.html">
<meta property="og:site_name" content="LeDao的博客">
<meta property="og:description" content="DockerFile简介dockerfile用于快速有序且直观地完成对镜像的定制 Dockerfile 是一个文本文件，其内包含了一条条的指令(Instruction)，每一条指令构建一层，因此每一条指令的内容，就是描述该层应当如何构建 指令FROMFROM指令是整个Dockerfile的入口，必须是第一条指令。其代表新制作镜像的基础镜像。基础镜像可以自己制作，也可以从开源的仓库pull，例如do">
<meta property="og:locale" content="zh_CN">
<meta property="og:image" content="https://image.zoutl.cn/hexo-blog/blogCoverImage/304.jpg">
<meta property="article:published_time" content="2021-08-21T13:38:01.000Z">
<meta property="article:modified_time" content="2022-03-26T16:58:49.140Z">
<meta property="article:author" content="LeDao">
<meta property="article:tag" content="Docker">
<meta property="article:tag" content="DockerFile">
<meta name="twitter:card" content="summary">
<meta name="twitter:image" content="https://image.zoutl.cn/hexo-blog/blogCoverImage/304.jpg"><link rel="shortcut icon" href="/img/favicon.png"><link rel="canonical" href="https://blog.zoutl.cn/304"><link rel="preconnect" href="//cdn.jsdelivr.net"/><link rel="preconnect" href="//hm.baidu.com"/><link rel="preconnect" href="//busuanzi.ibruce.info"/><meta name="baidu-site-verification" content="fp2ohQruhOqzbyAh"/><link rel="stylesheet" href="/css/index.css"><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free/css/all.min.css" media="print" onload="this.media='all'"><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/node-snackbar/dist/snackbar.min.css" media="print" onload="this.media='all'"><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/instantsearch.js@2.10.5/dist/instantsearch.min.css" media="print" onload="this.media='all'"><script src="https://cdn.jsdelivr.net/npm/instantsearch.js@2.10.5/dist/instantsearch.min.js" defer></script><script>var _hmt = _hmt || [];
(function() {
  var hm = document.createElement("script");
  hm.src = "https://hm.baidu.com/hm.js?112c188c9864ee3c98ba7e2495734acf";
  var s = document.getElementsByTagName("script")[0]; 
  s.parentNode.insertBefore(hm, s);
})();
</script><script>const GLOBAL_CONFIG = { 
  root: '/',
  algolia: {"appId":"0Z2QSKFGM6","apiKey":"079e96e1d3e15e7f2f512596bf590eac","indexName":"hexo_blog","hits":{"per_page":6},"languages":{"input_placeholder":"搜索文章","hits_empty":"找不到您查询的内容：${query}","hits_stats":"找到 ${hits} 条结果，用时 ${time} 毫秒"}},
  localSearch: undefined,
  translate: undefined,
  noticeOutdate: undefined,
  highlight: {"plugin":"highlighjs","highlightCopy":true,"highlightLang":true,"highlightHeightLimit":false},
  copy: {
    success: '复制成功',
    error: '复制错误',
    noSupport: '浏览器不支持'
  },
  relativeDate: {
    homepage: false,
    post: false
  },
  runtime: '天',
  date_suffix: {
    just: '刚刚',
    min: '分钟前',
    hour: '小时前',
    day: '天前',
    month: '个月前'
  },
  copyright: undefined,
  lightbox: 'fancybox',
  Snackbar: {"chs_to_cht":"你已切换为繁体","cht_to_chs":"你已切换为简体","day_to_night":"你已切换为深色模式","night_to_day":"你已切换为浅色模式","bgLight":"#49b1f5","bgDark":"#121212","position":"top-center"},
  source: {
    jQuery: 'https://cdn.jsdelivr.net/npm/jquery@latest/dist/jquery.min.js',
    justifiedGallery: {
      js: 'https://cdn.jsdelivr.net/npm/justifiedGallery/dist/js/jquery.justifiedGallery.min.js',
      css: 'https://cdn.jsdelivr.net/npm/justifiedGallery/dist/css/justifiedGallery.min.css'
    },
    fancybox: {
      js: 'https://cdn.jsdelivr.net/npm/@fancyapps/fancybox@latest/dist/jquery.fancybox.min.js',
      css: 'https://cdn.jsdelivr.net/npm/@fancyapps/fancybox@latest/dist/jquery.fancybox.min.css'
    }
  },
  isPhotoFigcaption: false,
  islazyload: false,
  isanchor: true
}</script><script id="config-diff">var GLOBAL_CONFIG_SITE = {
  title: 'DockerFile常用指令',
  isPost: true,
  isHome: false,
  isHighlightShrink: false,
  isToc: true,
  postUpdate: '2022-03-27 00:58:49'
}</script><noscript><style type="text/css">
  #nav {
    opacity: 1
  }
  .justified-gallery img {
    opacity: 1
  }

  #recent-posts time,
  #post-meta time {
    display: inline !important
  }
</style></noscript><script>(win=>{
    win.saveToLocal = {
      set: function setWithExpiry(key, value, ttl) {
        if (ttl === 0) return
        const now = new Date()
        const expiryDay = ttl * 86400000
        const item = {
          value: value,
          expiry: now.getTime() + expiryDay,
        }
        localStorage.setItem(key, JSON.stringify(item))
      },

      get: function getWithExpiry(key) {
        const itemStr = localStorage.getItem(key)

        if (!itemStr) {
          return undefined
        }
        const item = JSON.parse(itemStr)
        const now = new Date()

        if (now.getTime() > item.expiry) {
          localStorage.removeItem(key)
          return undefined
        }
        return item.value
      }
    }
  
    win.getScript = url => new Promise((resolve, reject) => {
      const script = document.createElement('script')
      script.src = url
      script.async = true
      script.onerror = reject
      script.onload = script.onreadystatechange = function() {
        const loadState = this.readyState
        if (loadState && loadState !== 'loaded' && loadState !== 'complete') return
        script.onload = script.onreadystatechange = null
        resolve()
      }
      document.head.appendChild(script)
    })
  
      win.activateDarkMode = function () {
        document.documentElement.setAttribute('data-theme', 'dark')
        if (document.querySelector('meta[name="theme-color"]') !== null) {
          document.querySelector('meta[name="theme-color"]').setAttribute('content', '#0d0d0d')
        }
      }
      win.activateLightMode = function () {
        document.documentElement.setAttribute('data-theme', 'light')
        if (document.querySelector('meta[name="theme-color"]') !== null) {
          document.querySelector('meta[name="theme-color"]').setAttribute('content', '#ffffff')
        }
      }
      const t = saveToLocal.get('theme')
    
          if (t === 'dark') activateDarkMode()
          else if (t === 'light') activateLightMode()
        
      const asideStatus = saveToLocal.get('aside-status')
      if (asideStatus !== undefined) {
        if (asideStatus === 'hide') {
          document.documentElement.classList.add('hide-aside')
        } else {
          document.documentElement.classList.remove('hide-aside')
        }
      }
    
    const fontSizeVal = saveToLocal.get('global-font-size')
    if (fontSizeVal !== undefined) {
      document.documentElement.style.setProperty('--global-font-size', fontSizeVal + 'px')
    }
    
    const detectApple = () => {
      if (GLOBAL_CONFIG_SITE.isHome && /iPad|iPhone|iPod|Macintosh/.test(navigator.userAgent)){
        document.documentElement.classList.add('apple')
      }
    }
    detectApple()
    })(window)</script><link rel="stylesheet" href="//at.alicdn.com/t/font_3265865_ia5ii2b8gxh.css"><meta name="generator" content="Hexo 5.4.0"><link rel="alternate" href="/atom.xml" title="LeDao的博客" type="application/atom+xml">
<style>.darkmode--activated{--body-bg-color:#282828;--content-bg-color:#333;--card-bg-color:#555;--text-color:#ccc;--blockquote-color:#bbb;--link-color:#ccc;--link-hover-color:#eee;--brand-color:#ddd;--brand-hover-color:#ddd;--table-row-odd-bg-color:#282828;--table-row-hover-bg-color:#363636;--menu-item-bg-color:#555;--btn-default-bg:#222;--btn-default-color:#ccc;--btn-default-border-color:#555;--btn-default-hover-bg:#666;--btn-default-hover-color:#ccc;--btn-default-hover-border-color:#666;--highlight-background:#282b2e;--highlight-foreground:#a9b7c6;--highlight-gutter-background:#34393d;--highlight-gutter-foreground:#9ca9b6}.darkmode--activated img{opacity:.75}.darkmode--activated img:hover{opacity:.9}.darkmode--activated code{color:#69dbdc;background:0 0}button.darkmode-toggle{z-index:9999}</style></head><body><div id="loading-box"><div class="loading-left-bg"></div><div class="loading-right-bg"></div><div class="spinner-box"><div class="configure-border-1"><div class="configure-core"></div></div><div class="configure-border-2"><div class="configure-core"></div></div><div class="loading-word">加载中...</div></div></div><div id="sidebar"><div id="menu-mask"></div><div id="sidebar-menus"><div class="avatar-img is-center"><img src="https://image.zoutl.cn/hexo-blog/images/logo.png" onerror="onerror=null;src='/img/friend_404.gif'" alt="avatar"/></div><div class="site-data"><div class="data-item is-center"><div class="data-item-link"><a href="/archives/"><div class="headline">文章</div><div class="length-num">480</div></a></div></div><div class="data-item is-center"><div class="data-item-link"><a href="/tags/"><div class="headline">标签</div><div class="length-num">67</div></a></div></div><div class="data-item is-center"><div class="data-item-link"><a href="/categories/"><div class="headline">分类</div><div class="length-num">36</div></a></div></div></div><hr/><div class="menus_items"><div class="menus_item"><a class="site-page" href="/"><i class="fa-fw fas fa-home"></i><span> 首页</span></a></div><div class="menus_item"><a class="site-page" href="/archives/"><i class="fa-fw fas fa-archive"></i><span> 归档</span></a></div><div class="menus_item"><a class="site-page" href="/tags/"><i class="fa-fw fas fa-tags"></i><span> 标签</span></a></div><div class="menus_item"><a class="site-page" href="/categories/"><i class="fa-fw fas fa-folder-open"></i><span> 分类</span></a></div><div class="menus_item"><a class="site-page" href="javascript:void(0);" rel="external nofollow noreferrer"><i class="fa-fw iconfont icon-ziyuan218"></i><span> 其它</span><i class="fas fa-chevron-down expand"></i></a><ul class="menus_item_child"><li><a class="site-page child" href="/gallery/"><i class="fa-fw fas fa-image"></i><span> 壁纸</span></a></li></ul></div></div></div></div><div class="post" id="body-wrap"><header class="post-bg" id="page-header" style="background-image: url('https://image.zoutl.cn/hexo-blog/blogCoverImage/304.jpg')"><nav id="nav"><span id="blog_name"><a id="site-name" href="/">LeDao的博客</a></span><div id="menus"><div id="search-button"><a class="site-page social-icon search"><i class="fas fa-search fa-fw"></i><span> 搜索</span></a></div><div class="menus_items"><div class="menus_item"><a class="site-page" href="/"><i class="fa-fw fas fa-home"></i><span> 首页</span></a></div><div class="menus_item"><a class="site-page" href="/archives/"><i class="fa-fw fas fa-archive"></i><span> 归档</span></a></div><div class="menus_item"><a class="site-page" href="/tags/"><i class="fa-fw fas fa-tags"></i><span> 标签</span></a></div><div class="menus_item"><a class="site-page" href="/categories/"><i class="fa-fw fas fa-folder-open"></i><span> 分类</span></a></div><div class="menus_item"><a class="site-page" href="javascript:void(0);" rel="external nofollow noreferrer"><i class="fa-fw iconfont icon-ziyuan218"></i><span> 其它</span><i class="fas fa-chevron-down expand"></i></a><ul class="menus_item_child"><li><a class="site-page child" href="/gallery/"><i class="fa-fw fas fa-image"></i><span> 壁纸</span></a></li></ul></div></div><div id="toggle-menu"><a class="site-page"><i class="fas fa-bars fa-fw"></i></a></div></div></nav><div id="post-info"><h1 class="post-title">DockerFile常用指令</h1><div id="post-meta"><div class="meta-firstline"><span class="post-meta-date"><i class="far fa-calendar-alt fa-fw post-meta-icon"></i><span class="post-meta-label">发表于</span><time class="post-meta-date-created" datetime="2021-08-21T13:38:01.000Z" title="发表于 2021-08-21 21:38:01">2021-08-21</time><span class="post-meta-separator">|</span><i class="fas fa-history fa-fw post-meta-icon"></i><span class="post-meta-label">更新于</span><time class="post-meta-date-updated" datetime="2022-03-26T16:58:49.140Z" title="更新于 2022-03-27 00:58:49">2022-03-27</time></span><span class="post-meta-categories"><span class="post-meta-separator">|</span><i class="fas fa-inbox fa-fw post-meta-icon"></i><a class="post-meta-categories" href="/categories/Docker/">Docker</a></span></div><div class="meta-secondline"><span class="post-meta-separator">|</span><span class="post-meta-wordcount"><i class="far fa-file-word fa-fw post-meta-icon"></i><span class="post-meta-label">字数总计:</span><span class="word-count">2.6k</span><span class="post-meta-separator">|</span><i class="far fa-clock fa-fw post-meta-icon"></i><span class="post-meta-label">阅读时长:</span><span>9分钟</span></span><span class="post-meta-separator">|</span><span class="post-meta-pv-cv" id="" data-flag-title="DockerFile常用指令"><i class="far fa-eye fa-fw post-meta-icon"></i><span class="post-meta-label">阅读量:</span><span id="busuanzi_value_page_pv"></span></span></div></div></div></header><main class="layout" id="content-inner"><div id="post"><article class="post-content" id="article-container"><h3 id="DockerFile简介"><a href="#DockerFile简介" class="headerlink" title="DockerFile简介"></a>DockerFile简介</h3><p>dockerfile用于快速有序且直观地完成对镜像的定制</p>
<p>Dockerfile 是一个文本文件，其内包含了一条条的指令(Instruction)，每一条指令构建一层，因此每一条指令的内容，就是描述该层应当如何构建</p>
<h3 id="指令"><a href="#指令" class="headerlink" title="指令"></a>指令</h3><h4 id="FROM"><a href="#FROM" class="headerlink" title="FROM"></a>FROM</h4><p>FROM指令是整个Dockerfile的入口，必须是第一条指令。其代表新制作镜像的基础镜像。基础镜像可以自己制作，也可以从开源的仓库pull，例如dockerhub或是国内阿里云的免费仓库。</p>
<p>Docker中存在一种特殊的情况，就是不以任何基础镜像为基准，此时可以第一句话使用：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">FROM scratch</span><br></pre></td></tr></table></figure>

<p>来表示以空白镜像为基础，也就是直接将可执行文件复制进镜像。例如swarm、coreos/etcd等。</p>
<h4 id="RUN指令"><a href="#RUN指令" class="headerlink" title="RUN指令"></a>RUN指令</h4><p>是dockerfile中最常用的指令之一。用来执行命令行上的命令。RUN的格式分为两种：</p>
<p>第一种：<br>shell格式：<code>RUN&lt;命令&gt;</code>，类似于直接在终端输入命令。例如：</p>
<figure class="highlight ruby"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">RUN echo <span class="string">&#x27;&lt;h1&gt;Hello, Docker!&lt;/h1&gt;&#x27;</span> &gt; <span class="regexp">/usr/share</span><span class="regexp">/tomcat/welcome</span>.html</span><br></pre></td></tr></table></figure>

<p>第二种：<br>exec格式：<code>RUN [&quot;可执行文件&quot;, &quot;参数1&quot;, &quot;参数2&quot;]</code>。<br>RUN既然可以像在命令行那样工作，那么就也可以实现传参来运行指令：</p>
<figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">FROM ubuntu:<span class="number">14.04</span></span><br><span class="line"></span><br><span class="line">RUN apt-get update</span><br><span class="line">RUN apt-get install -y gcc libc6-dev <span class="built_in">make</span></span><br><span class="line">RUN wget -O redis.tar.gz <span class="string">&quot;http://download.redis.io/releases/redis-3.2.5.tar.gz&quot;</span></span><br><span class="line">RUN mkdir -p /usr/src/redis</span><br><span class="line">RUN tar -xzf redis.tar.gz -C /usr/src/redis --strip-components=<span class="number">1</span></span><br><span class="line">RUN <span class="built_in">make</span> -C /usr/src/redis</span><br><span class="line">RUN <span class="built_in">make</span> -C /usr/src/redis install</span><br></pre></td></tr></table></figure>

<p>RUN一次就代表Dockerfile中的一层。而docker镜像的构建就是不断去完善每一层需要做的事情。而dockerfi对一个file中层数是有限制的，最大不超过127层。因此，RUN提供命令的串联功能，也就是允许每一层可包含多种操作，他们会按照书写顺序来依次执行。那么上面的例子可以变为：</p>
<figure class="highlight csharp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">FROM ubuntu:<span class="number">14.04</span></span><br><span class="line">RUN buildDeps=<span class="string">&#x27;gcc libc6-dev make&#x27;</span> \</span><br><span class="line">    &amp;&amp; apt-<span class="keyword">get</span> update \</span><br><span class="line">    &amp;&amp; apt-<span class="keyword">get</span> install -y $buildDeps \</span><br><span class="line">    &amp;&amp; wget -O redis.tar.gz <span class="string">&quot;http://download.redis.io/releases/redis-3.2.5.tar.gz&quot;</span> \</span><br><span class="line">    &amp;&amp; mkdir -p /usr/src/redis \</span><br><span class="line">    &amp;&amp; tar -xzf redis.tar.gz -C /usr/src/redis --strip-components=<span class="number">1</span> \</span><br><span class="line">    &amp;&amp; make -C /usr/src/redis \</span><br><span class="line">    &amp;&amp; make -C /usr/src/redis install \</span><br><span class="line">    &amp;&amp; rm -rf /<span class="keyword">var</span>/lib/apt/lists<span class="comment">/* \</span></span><br><span class="line"><span class="comment">    &amp;&amp; rm redis.tar.gz \</span></span><br><span class="line"><span class="comment">    &amp;&amp; rm -r /usr/src/redis \</span></span><br><span class="line"><span class="comment">    &amp;&amp; apt-get purge -y --auto-remove $buildDeps</span></span><br></pre></td></tr></table></figure>

<p>换行用 \ ，注释用 # ，平时书写注意缩进来保证文件的可读性。上述例子中的最后一句还进行了无关文件的清理，进一步保证每一层的最优和最小</p>
<p>注意事项：<br>镜像的初衷是进行功能的模块化，也是尽可能让每个容器干最少的事情，那么我们在书写dockerfile的时候要注意这个问题，每一层的东西确保是必须的，否则就不要进行安装或是拷贝。</p>
<h4 id="MAINTAINER"><a href="#MAINTAINER" class="headerlink" title="MAINTAINER"></a>MAINTAINER</h4><p>指定作者<br>句法：</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">MAINTAINER <span class="tag">&lt;<span class="name">name</span>&gt;</span></span><br></pre></td></tr></table></figure>

<h4 id="LABEL"><a href="#LABEL" class="headerlink" title="LABEL"></a>LABEL</h4><p>该指令是为镜像添加标签<br>句法：</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">LABEL <span class="tag">&lt;<span class="name">key</span>&gt;</span>=<span class="tag">&lt;<span class="name">value</span>&gt;</span> <span class="tag">&lt;<span class="name">key</span>&gt;</span>=<span class="tag">&lt;<span class="name">value</span>&gt;</span> <span class="tag">&lt;<span class="name">key</span>&gt;</span>=<span class="tag">&lt;<span class="name">value</span>&gt;</span> ...</span><br></pre></td></tr></table></figure>

<p>一个Dockerfile种可以有多个LABEL，如下：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">LABEL multi.label1=<span class="string">&quot;value1&quot;</span> \</span><br><span class="line">multi.label2=<span class="string">&quot;value2&quot;</span> \</span><br><span class="line">other=<span class="string">&quot;value3&quot;</span></span><br></pre></td></tr></table></figure>

<p>说明：LABEL会继承基础镜像种的LABEL，如遇到key相同，则值覆盖</p>
<h4 id="COPY指令"><a href="#COPY指令" class="headerlink" title="COPY指令"></a>COPY指令</h4><p>该指令用于将宿主机文件拷贝至镜像内的指定路径<br>格式：</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">COPY &lt;源路径&gt;... &lt;目标路径&gt;</span><br><span class="line">或</span><br><span class="line">COPY [&quot;&lt;源路径1&gt;&quot;,... &quot;&lt;目标路径&gt;&quot;]</span><br></pre></td></tr></table></figure>

<p>也就是说，原路径可以有多个，而目标路径唯一<br>注意事项：</p>
<p>1、可以使用符合GO规范的通配符，例如：<code>COPY hom* /mydir/</code><br>2、目的路径可以是镜像内的绝对路径，也可以是相对于当前工作目录的相对路径<br>3、COPY过来的文件权限与原始权限相同。如需更改，请用传统Liunx的chmod命令进行修改即可</p>
<h4 id="ADD高级复制"><a href="#ADD高级复制" class="headerlink" title="ADD高级复制"></a>ADD高级复制</h4><p>ADD的本质作用类似于COPY，但是其更复杂：</p>
<p>1、ADD过来的压缩包可以自动在目标路径下进行解压<br>2、原始路径可以是一个连接，ADD过程会尝试从该链接下载所需的文件到目的路径<br>3、一般情况下，建议使用COPY而不是ADD，因为COPY过来的文件可以配合使用RUN来进行解压或是其他操作，搭配使用更灵活，且单条语句所负担的功能唯一</p>
<h4 id="WORKDIR"><a href="#WORKDIR" class="headerlink" title="WORKDIR"></a>WORKDIR</h4><p>该指令用于指定Dockerfile中该指令下面的操作所在的工作目录<br>类似于 cd 命令</p>
<h4 id="CMD-服务启动指令"><a href="#CMD-服务启动指令" class="headerlink" title="CMD 服务启动指令"></a>CMD 服务启动指令</h4><p>Docker不是虚拟机而是一个进程，作为进程，当然可以制定启动镜像时的具体参数。说白了就是制定一些你想自动启动的服务<br>格式：</p>
<figure class="highlight objectivec"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">shell 格式：<span class="built_in">CMD</span> &lt;命令&gt;</span><br><span class="line">exec 格式：<span class="built_in">CMD</span> [<span class="string">&quot;可执行文件&quot;</span>, <span class="string">&quot;参数1&quot;</span>, <span class="string">&quot;参数2&quot;</span>...]</span><br><span class="line">参数列表格式：<span class="built_in">CMD</span> [<span class="string">&quot;参数1&quot;</span>, <span class="string">&quot;参数2&quot;</span>...]。在指定了 ENTRYPOINT 指令后，用 <span class="built_in">CMD</span> 指定具体的参数。</span><br></pre></td></tr></table></figure>

<p>注意事项：</p>
<p>1、CMD中的启动参数可以被更新覆盖。例如：<br>Dockerfile中若是用CMD指定启动镜像时执行/bin/bash，那么在启动镜像时输入<code>docker run -it ubuntu ./test.sh</code> 则会用./test.sh命令来覆盖/bin/bash命令<br>2、推荐使用exec格式的CMD书写。这类格式在解析时会被解析为 JSON 数组，因此一定要使用双引号 “，而不要使用单引号<br>3、如果使用 shell 格式的话，实际的命令会被包装为 sh -c 的参数的形式进行执行。比如：<code>CMD echo /java</code><br>在实际执行中，会将其变更为：<br><code>CMD [ &quot;sh&quot;, &quot;-c&quot;, &quot;echo /java&quot; ]</code></p>
<h4 id="ENV设置环境变量"><a href="#ENV设置环境变量" class="headerlink" title="ENV设置环境变量"></a>ENV设置环境变量</h4><p>说是环境变量还不说是一个全局变量。在前面定义，后面可以通过 $ 取值进行使用<br>格式：</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">ENV <span class="tag">&lt;<span class="name">key</span>&gt;</span> <span class="tag">&lt;<span class="name">value</span>&gt;</span></span><br><span class="line">ENV <span class="tag">&lt;<span class="name">key1</span>&gt;</span>=<span class="tag">&lt;<span class="name">value1</span>&gt;</span> <span class="tag">&lt;<span class="name">key2</span>&gt;</span>=<span class="tag">&lt;<span class="name">value2</span>&gt;</span>...</span><br></pre></td></tr></table></figure>

<p>例如可以指定一些包的版本号，这样更新镜像很方便，或是保存一些密码（该功能慎用，自己玩还是可以的）</p>
<h4 id="ARG-构建参数"><a href="#ARG-构建参数" class="headerlink" title="ARG 构建参数"></a>ARG 构建参数</h4><p>语法形式: <code>ARG &lt;name&gt;[=&lt;default value&gt;]</code><br>ARG和ENV效果类似，都是用来设置观景变量的。唯一 不同的是dockerfile中的ARG编译好后是不会出现在打开的容器内的</p>
<p>ARG在dockerfile中创建一个全局参数，参数可以给定一个默认值，在编译时可以传参对其进行覆盖。如果ARG指令有默认值并且在构建期间没有接收到参数、则使用默认值。一个dockerfile中可以包含多个ARG参数</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">docker build --build-arg <span class="tag">&lt;<span class="name">varname</span>&gt;</span>=<span class="tag">&lt;<span class="name">value</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p>可以使用ARG或ENV指令来指定RUN指令可用的变量，如果ARG和ENV同时指定了一个相同名称的变量、则ENV设置的变量会覆盖ARG设置的变量。如下:</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">1 FROM ubuntu</span><br><span class="line">2 ARG CONT_IMG_VER</span><br><span class="line">3 ENV CONT_IMG_VER v1.0.0</span><br><span class="line">4 RUN <span class="built_in">echo</span> <span class="variable">$CONT_IMG_VER</span></span><br></pre></td></tr></table></figure>

<p>使用   <code>docker build --build-arg CONT_IMG_VER=v2.0.1 .</code> 最终输出v1.0.0 </p>
<p>一个ARG指令的有效范围在其定义的构建阶段内、如果要在多个阶段中都有效、则必须在每个阶段都使用ARG指令；<strong>与ARG不同  ENV设置参数的有效期为整个构建期内</strong></p>
<h4 id="VOLUME-挂在共享卷"><a href="#VOLUME-挂在共享卷" class="headerlink" title="VOLUME 挂在共享卷"></a>VOLUME 挂在共享卷</h4><p>格式为：</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">VOLUME [&quot;&lt;路径1&gt;&quot;, &quot;&lt;路径2&gt;&quot;...]</span><br><span class="line">VOLUME &lt;路径&gt;</span><br></pre></td></tr></table></figure>

<p>Docker的使用原则除了每个容器干尽量少的事情外，还尽可能要求容器运行时应该尽量保持容器存储层不发生写操作，对于数据库类需要保存动态数据的应用，其数据库文件应该保存于卷(volume)中，也就是将本地磁盘的某一个目录挂载至容器内。同时这样的共享目录可以被多个不同的容器所使用</p>
<p>除了可以在dockerfile中指定这一参数外，在运行启动容器时也可以附带这一参数来指定共享卷：</p>
<figure class="highlight kotlin"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">docker run -it --name container-test -h CONTAINER -v /<span class="keyword">data</span> debian /bin/bash</span><br></pre></td></tr></table></figure>

<p>上述命令也可以覆盖dockerfile中的目录设定。</p>
<h4 id="USER指定用户"><a href="#USER指定用户" class="headerlink" title="USER指定用户"></a>USER指定用户</h4><p>在书写dockerfile时，某些层的操作若想切换用户名，可以使用该参数指定某些层的用户，并且是存在的用户名。<br> 格式：<code>USER &lt;用户名&gt;</code></p>
<p>如果以 <code>root</code> 执行的脚本，在执行期间希望改变身份，比如希望以某个已经建立好的用户来运行某个服务进程，不要使用 <code>su</code> 或者 <code>sudo</code>，这些都需要比较麻烦的配置，而且在 TTY 缺失的环境下经常出错。建议使用 <code>gosu</code></p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 建立 redis 用户，并使用 gosu 换另一个用户执行命令</span></span><br><span class="line">RUN groupadd -r redis &amp;&amp; useradd -r -g redis redis</span><br><span class="line"><span class="comment"># 下载 gosu</span></span><br><span class="line">RUN wget -O /usr/<span class="built_in">local</span>/bin/gosu <span class="string">&quot;https://github.com/tianon/gosu/releases/download/1.7/gosu-amd64&quot;</span> \</span><br><span class="line">    &amp;&amp; chmod +x /usr/<span class="built_in">local</span>/bin/gosu \</span><br><span class="line">    &amp;&amp; gosu nobody <span class="literal">true</span></span><br><span class="line"><span class="comment"># 设置 CMD，并以另外的用户执行</span></span><br><span class="line">CMD [ <span class="string">&quot;exec&quot;</span>, <span class="string">&quot;gosu&quot;</span>, <span class="string">&quot;redis&quot;</span>, <span class="string">&quot;redis-server&quot;</span> ]</span><br></pre></td></tr></table></figure>

<h4 id="EXPOSE暴漏端口"><a href="#EXPOSE暴漏端口" class="headerlink" title="EXPOSE暴漏端口"></a>EXPOSE暴漏端口</h4><p>句法：</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">EXPOSE &lt;端口1&gt; [&lt;端口2&gt;...]</span><br></pre></td></tr></table></figure>

<p><code>EXPOSE</code> 指令是声明运行时容器提供服务端口，这只是一个声明，在运行时并不会因为这个声明应用就会开启这个端口的服务。在 Dockerfile 中写入这样的声明有两个好处，一个是帮助镜像使用者理解这个镜像服务的守护端口，以方便配置映射；另一个用处则是在运行时使用随机端口映射时，也就是 <code>docker run -P</code> 时，会自动随机映射 <code>EXPOSE</code> 的端口</p>
<p>要将 EXPOSE 和在运行时使用 <code>-p &lt;宿主端口&gt;:&lt;容器端口&gt;</code> 区分开来。<code>-p</code>，是映射宿主端口和容器端口，换句话说，就是将容器的对应端口服务公开给外界访问，而 EXPOSE 仅仅是声明容器打算使用什么端口而已，并不会自动在宿主进行端口映射</p>
<h3 id="PS"><a href="#PS" class="headerlink" title="PS."></a>PS.</h3><p>来源：<a target="_blank" rel="noopener external nofollow noreferrer" href="https://www.jianshu.com/p/2a90fc6ee383">https://www.jianshu.com/p/2a90fc6ee383</a></p>
</article><div class="post-copyright"><div class="post-copyright__author"><span class="post-copyright-meta">文章作者: </span><span class="post-copyright-info"><a href="mailto:undefined" rel="external nofollow noreferrer">LeDao</a></span></div><div class="post-copyright__type"><span class="post-copyright-meta">文章链接: </span><span class="post-copyright-info"><a href="https://blog.zoutl.cn/304.html">https://blog.zoutl.cn/304.html</a></span></div><div class="post-copyright__notice"><span class="post-copyright-meta">版权声明: </span><span class="post-copyright-info">本博客所有文章除特别声明外，均采用 <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/" rel="external nofollow noreferrer" target="_blank">CC BY-NC-SA 4.0</a> 许可协议。转载请注明来自 <a href="https://blog.zoutl.cn" target="_blank">LeDao的博客</a>！</span></div></div><div class="tag_share"><div class="post-meta__tag-list"><a class="post-meta__tags" href="/tags/Docker/">Docker</a><a class="post-meta__tags" href="/tags/DockerFile/">DockerFile</a></div><div class="post_share"></div></div><nav class="pagination-post" id="pagination"><div class="prev-post pull-left"><a href="/305.html"><img class="prev-cover" src="https://image.zoutl.cn/hexo-blog/blogCoverImage/305.jpg" onerror="onerror=null;src='/img/404.jpg'" alt="cover of previous post"><div class="pagination-info"><div class="label">上一篇</div><div class="prev_info">DockerFile构建自定义CentOS</div></div></a></div><div class="next-post pull-right"><a href="/303.html"><img class="next-cover" src="https://image.zoutl.cn/hexo-blog/blogCoverImage/303.jpg" onerror="onerror=null;src='/img/404.jpg'" alt="cover of next post"><div class="pagination-info"><div class="label">下一篇</div><div class="next_info">Docker备份和恢复镜像</div></div></a></div></nav><div class="relatedPosts"><div class="headline"><i class="fas fa-thumbs-up fa-fw"></i><span> 相关推荐</span></div><div class="relatedPosts-list"><div><a href="/305.html" title="DockerFile构建自定义CentOS"><img class="cover" src="https://image.zoutl.cn/hexo-blog/blogCoverImage/305.jpg" alt="cover"><div class="content is-center"><div class="date"><i class="far fa-calendar-alt fa-fw"></i> 2021-08-21</div><div class="title">DockerFile构建自定义CentOS</div></div></a></div><div><a href="/306.html" title="DockerFile构建自定义Tomcat"><img class="cover" src="https://image.zoutl.cn/hexo-blog/blogCoverImage/306.jpg" alt="cover"><div class="content is-center"><div class="date"><i class="far fa-calendar-alt fa-fw"></i> 2021-08-22</div><div class="title">DockerFile构建自定义Tomcat</div></div></a></div><div><a href="/307.html" title="DockerFile创建镜像时报错：file not found in build context or excluded by"><img class="cover" src="https://image.zoutl.cn/hexo-blog/blogCoverImage/307.jpg" alt="cover"><div class="content is-center"><div class="date"><i class="far fa-calendar-alt fa-fw"></i> 2021-08-22</div><div class="title">DockerFile创建镜像时报错：file not found in build context or excluded by</div></div></a></div><div><a href="/308.html" title="DockerFile通过VOLUME指令创建容器卷来实现容器的目录挂载"><img class="cover" src="https://image.zoutl.cn/hexo-blog/blogCoverImage/308.jpg" alt="cover"><div class="content is-center"><div class="date"><i class="far fa-calendar-alt fa-fw"></i> 2021-08-22</div><div class="title">DockerFile通过VOLUME指令创建容器卷来实现容器的目录挂载</div></div></a></div><div><a href="/309.html" title="DockerFile的CMD, ENTRYPOINT指令"><img class="cover" src="https://image.zoutl.cn/hexo-blog/blogCoverImage/309.jpg" alt="cover"><div class="content is-center"><div class="date"><i class="far fa-calendar-alt fa-fw"></i> 2021-08-22</div><div class="title">DockerFile的CMD, ENTRYPOINT指令</div></div></a></div><div><a href="/310.html" title="DockerFile的ONBUILD指令"><img class="cover" src="https://image.zoutl.cn/hexo-blog/blogCoverImage/310.jpg" alt="cover"><div class="content is-center"><div class="date"><i class="far fa-calendar-alt fa-fw"></i> 2021-08-23</div><div class="title">DockerFile的ONBUILD指令</div></div></a></div></div></div><hr/><div id="post-comment"><div class="comment-head"><div class="comment-headline"><i class="fas fa-comments fa-fw"></i><span> 评论</span></div></div><div class="comment-wrap"><div><div id="gitalk-container"></div></div></div></div></div><div class="aside-content" id="aside-content"><div class="sticky_layout"><div class="card-widget" id="card-toc"><div class="item-headline"><i class="fas fa-stream"></i><span>目录</span></div><div class="toc-content"><ol class="toc"><li class="toc-item toc-level-3"><a class="toc-link" href="#DockerFile%E7%AE%80%E4%BB%8B"><span class="toc-number">1.</span> <span class="toc-text">DockerFile简介</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E6%8C%87%E4%BB%A4"><span class="toc-number">2.</span> <span class="toc-text">指令</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#FROM"><span class="toc-number">2.1.</span> <span class="toc-text">FROM</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#RUN%E6%8C%87%E4%BB%A4"><span class="toc-number">2.2.</span> <span class="toc-text">RUN指令</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#MAINTAINER"><span class="toc-number">2.3.</span> <span class="toc-text">MAINTAINER</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#LABEL"><span class="toc-number">2.4.</span> <span class="toc-text">LABEL</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#COPY%E6%8C%87%E4%BB%A4"><span class="toc-number">2.5.</span> <span class="toc-text">COPY指令</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#ADD%E9%AB%98%E7%BA%A7%E5%A4%8D%E5%88%B6"><span class="toc-number">2.6.</span> <span class="toc-text">ADD高级复制</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#WORKDIR"><span class="toc-number">2.7.</span> <span class="toc-text">WORKDIR</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#CMD-%E6%9C%8D%E5%8A%A1%E5%90%AF%E5%8A%A8%E6%8C%87%E4%BB%A4"><span class="toc-number">2.8.</span> <span class="toc-text">CMD 服务启动指令</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#ENV%E8%AE%BE%E7%BD%AE%E7%8E%AF%E5%A2%83%E5%8F%98%E9%87%8F"><span class="toc-number">2.9.</span> <span class="toc-text">ENV设置环境变量</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#ARG-%E6%9E%84%E5%BB%BA%E5%8F%82%E6%95%B0"><span class="toc-number">2.10.</span> <span class="toc-text">ARG 构建参数</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#VOLUME-%E6%8C%82%E5%9C%A8%E5%85%B1%E4%BA%AB%E5%8D%B7"><span class="toc-number">2.11.</span> <span class="toc-text">VOLUME 挂在共享卷</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#USER%E6%8C%87%E5%AE%9A%E7%94%A8%E6%88%B7"><span class="toc-number">2.12.</span> <span class="toc-text">USER指定用户</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#EXPOSE%E6%9A%B4%E6%BC%8F%E7%AB%AF%E5%8F%A3"><span class="toc-number">2.13.</span> <span class="toc-text">EXPOSE暴漏端口</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#PS"><span class="toc-number">3.</span> <span class="toc-text">PS.</span></a></li></ol></div></div></div></div></main><footer id="footer" style="background-image: url('https://image.zoutl.cn/hexo-blog/blogCoverImage/304.jpg')"><div id="footer-wrap"><div class="copyright">&copy;2020 - 2022&nbsp;<i style="color:red;animation: announ_animation 0.8s linear infinite;"class="fa fa-heartbeat"></i> By LeDao</div><div class="footer_custom_text"><span>本网站由</span><a target="_blank" rel="noopener external nofollow noreferrer" href="https://www.upyun.com/?utm_source=lianmeng&utm_medium=referral"><img class="icp-icon" src="https://image.zoutl.cn/hexo-blog/images/%E5%8F%88%E6%8B%8D%E4%BA%91_logo2.png"></a><span>提供CDN加速/云存储服务</span><br/><a target="_blank" rel="noopener external nofollow noreferrer" href="https://beian.miit.gov.cn/">桂ICP备20005695号 </a><img src='https://image.zoutl.cn/hexo-blog/images/beian.png'><a target="_blank" rel="noopener external nofollow noreferrer" href="http://www.beian.gov.cn/portal/registerSystemInfo?recordcode=45098102000418"> 桂公网安备45098102000418号</a></div></div></footer></div><div id="rightside"><div id="rightside-config-hide"><button id="readmode" type="button" title="阅读模式"><i class="fas fa-book-open"></i></button><button id="font-plus" type="button" title="放大字体"><i class="fas fa-plus"></i></button><button id="font-minus" type="button" title="缩小字体"><i class="fas fa-minus"></i></button><button id="darkmode" type="button" title="浅色和深色模式转换"><i class="fas fa-adjust"></i></button><button id="hide-aside-btn" type="button" title="单栏和双栏切换"><i class="fas fa-arrows-alt-h"></i></button></div><div id="rightside-config-show"><button id="rightside_config" type="button" title="设置"><i class="fas fa-cog fa-spin"></i></button><button class="close" id="mobile-toc-button" type="button" title="目录"><i class="fas fa-list-ul"></i></button><a id="to_comment" href="#post-comment" title="直达评论"><i class="fas fa-comments"></i></a><button id="go-up" type="button" title="回到顶部"><i class="fas fa-arrow-up"></i></button></div></div><div id="algolia-search"><div class="search-dialog"><div class="search-dialog__title" id="algolia-search-title">Algolia</div><div id="algolia-input-panel"><div id="algolia-search-input"></div></div><hr/><div id="algolia-search-results"><div id="algolia-hits"></div><div id="algolia-pagination"></div><div id="algolia-stats"></div></div><span class="search-close-button"><i class="fas fa-times"></i></span></div><div id="search-mask"></div></div><div><script src="/js/utils.js"></script><script src="/js/main.js"></script><script src="https://cdn.jsdelivr.net/npm/node-snackbar/dist/snackbar.min.js"></script><script>function panguFn () {
  if (typeof pangu === 'object') pangu.autoSpacingPage()
  else {
    getScript('https://cdn.jsdelivr.net/npm/pangu/dist/browser/pangu.min.js')
      .then(() => {
        pangu.autoSpacingPage()
      })
  }
}

function panguInit () {
  if (false){
    GLOBAL_CONFIG_SITE.isPost && panguFn()
  } else {
    panguFn()
  }
}

document.addEventListener('DOMContentLoaded', panguInit)</script><script src="/js/search/algolia.js"></script><script>var preloader = {
  endLoading: () => {
    document.body.style.overflow = 'auto';
    document.getElementById('loading-box').classList.add("loaded")
  },
  initLoading: () => {
    document.body.style.overflow = '';
    document.getElementById('loading-box').classList.remove("loaded")

  }
}
window.addEventListener('load',preloader.endLoading())</script><div class="js-pjax"><script>function addGitalkSource () {
  const ele = document.createElement('link')
  ele.rel = 'stylesheet'
  ele.href= 'https://cdn.jsdelivr.net/npm/gitalk/dist/gitalk.min.css'
  document.getElementsByTagName('head')[0].appendChild(ele)
}

function loadGitalk () {
  function initGitalk () {
    var gitalk = new Gitalk(Object.assign({
      clientID: 'e85b530ea329d17050fe',
      clientSecret: '47090eb530100dd0d587d4e4a23de09b8c25d44d',
      repo: 'a6678696.github.io',
      owner: 'a6678696',
      admin: ['a6678696'],
      id: 'ec97079bdcaa1b9e2423da05a1041a73',
      language: 'zh-CN',
      perPage: 10,
      distractionFreeMode: false,
      pagerDirection: 'last',
      createIssueManually: false,
      updateCountCallback: commentCount
    },null))

    gitalk.render('gitalk-container')
  }

  if (typeof Gitalk === 'function') initGitalk()
  else {
    addGitalkSource()
    getScript('https://cdn.jsdelivr.net/npm/gitalk@latest/dist/gitalk.min.js').then(initGitalk)
  }
}

function commentCount(n){
  let isCommentCount = document.querySelector('#post-meta .gitalk-comment-count')
  if (isCommentCount) {
    isCommentCount.innerHTML= n
  }
}

if ('Gitalk' === 'Gitalk' || !false) {
  if (false) btf.loadComment(document.getElementById('gitalk-container'), loadGitalk)
  else loadGitalk()
} else {
  function loadOtherComment () {
    loadGitalk()
  }
}</script></div><script defer="defer" id="ribbon" src="https://cdn.jsdelivr.net/npm/butterfly-extsrc@1/dist/canvas-ribbon.min.js" size="150" alpha="0.6" zIndex="-1" mobile="false" data-click="true"></script><script src="https://cdn.jsdelivr.net/npm/butterfly-extsrc@1/dist/activate-power-mode.min.js"></script><script>POWERMODE.colorful = true;
POWERMODE.shake = true;
POWERMODE.mobile = false;
document.body.addEventListener('input', POWERMODE);
</script><script id="click-heart" src="https://cdn.jsdelivr.net/npm/butterfly-extsrc@1/dist/click-heart.min.js" async="async" mobile="false"></script><script async data-pjax src="//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script></div></body></html>